﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using IWMAG.Scripting.Types;
using IWMAG.Scripting.AST;
using System.Reflection;
using IWMAG.Scripting.Interpreter;

namespace IWMAG.Scripting.Helpers {
    public class CompileTable {
        public SymbolTable<string, CodeType> Variables = new SymbolTable<string, CodeType>();
        public SymbolTable<string, Signature> Functions = new SymbolTable<string, Signature>();
        public SymbolTable<ReferenceType, Type> Imports = new SymbolTable<ReferenceType,Type>();
        public SymbolTable<ReferenceType, CodeType> Aliases = new SymbolTable<ReferenceType, CodeType>();
        public SymbolTable<Type, Func<object>> Lookahead = new SymbolTable<Type, Func<object>>();
        public ScriptEngine Engine;

        public CompileTable Parent {
            set {
                Variables.Parent = value.Variables;
                Functions.Parent = value.Functions;
                Imports.Parent = value.Imports;
                Aliases.Parent = value.Aliases;
                Lookahead.Parent = value.Lookahead;
            }
        }

        public void OpenScope() {
            Variables.OpenScope();
            Functions.OpenScope();
            Imports.OpenScope();
            Aliases.OpenScope();
            Lookahead.OpenScope();
        }

        public void CloseScope() {
            Variables.CloseScope();
            Functions.CloseScope();
            Imports.CloseScope();
            Aliases.CloseScope();
            Lookahead.CloseScope();
        }

        public CodeType Dealias(CodeType from) {
            while (from is ReferenceType && Aliases.Contains(from as ReferenceType)) {
                from = Aliases[from as ReferenceType];
            }

            return from;
        }

        public bool TypeExists(CodeType from) {
            from = Dealias(from);
            if (from is PrimitiveType) {
                return true;
            } else if (from is ArrayType) {
                return TypeExists((from as ArrayType).BaseType);
            } else if (from is ReferenceType) {
                return Imports.Contains(from as ReferenceType);
            }
            return false;
        }
    }
}
